package com.ocom.common.utils;

import com.ocom.common.entity.typehandler.PersonInfoHandle;

import java.util.*;

public class PasswordValidator {

    // 常见弱密码列表（实际使用时应从外部存储加载）
    private static final Set<String> WEAK_PASSWORDS = new HashSet<>(Arrays.asList(
            "password", "12345678", "admin123", "qwertyui", "abc12345",
            "p@ssw0rd", "welcome1", "password1", "Aa123456", "1234567890"
    ));

    // 特殊字符集合（根据等保要求自定义）
    private static final String SPECIAL_CHARS = "!@#$%^&*()_+-=[]{}|;:,.<>?";

    /**
     * 验证密码是否符合三级等保要求
     * @param password 待验证的密码
     * @return 错误信息列表（空列表表示验证通过）
     */
    public static List<String> validatePassword(String password) {
        List<String> errors = new ArrayList<>();

        if (password == null) {
            errors.add("密码不能为空");
            return errors;
        }

        // 1. 长度验证 (8-30位)
        if (password.length() < 8) {
            errors.add("密码长度至少8位");
        } else if (password.length() > 30) {
            errors.add("密码长度不能超过30位");
        }

        // 2. 空格检查
        if (password.contains(" ")) {
            errors.add("密码不能包含空格");
        }

        // 3. 字符类型计数器
        boolean hasUpper = false;
        boolean hasLower = false;
        boolean hasDigit = false;
        boolean hasSpecial = false;

        for (char c : password.toCharArray()) {
            if (Character.isUpperCase(c)) hasUpper = true;
            else if (Character.isLowerCase(c)) hasLower = true;
            else if (Character.isDigit(c)) hasDigit = true;
            else if (SPECIAL_CHARS.indexOf(c) != -1) hasSpecial = true;
        }

        // 4. 复杂度验证（至少包含三种字符类型）
        int typeCount = 0;
        if (hasUpper) typeCount++;
        if (hasLower) typeCount++;
        if (hasDigit) typeCount++;
        if (hasSpecial) typeCount++;

        if (typeCount < 3) {
            errors.add("密码必须包含大写字母、小写字母、数字、特殊字符(" + SPECIAL_CHARS + ")中至少三种");
        }

        // 5. 弱密码检查
        if (WEAK_PASSWORDS.contains(password.toLowerCase())) {
            errors.add("密码过于简单，请避免使用常见密码");
        }

        // 6. 连续字符检查（如123, abc等）
        if (hasSequentialChars(password, 3)) {
            errors.add("密码不能包含3位及以上连续字符");
        }

        // 7. 重复字符检查
        if (hasRepeatedChars(password, 4)) {
            errors.add("密码不能包含4位及以上重复字符");
        }

        return errors;
    }

    // 检查连续字符（升序/降序）
    private static boolean hasSequentialChars(String str, int sequenceLength) {
        for (int i = 0; i <= str.length() - sequenceLength; i++) {
            String substr = str.substring(i, i + sequenceLength);
            if (isConsecutive(substr)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isConsecutive(String substr) {
        boolean ascending = true;
        boolean descending = true;

        for (int j = 1; j < substr.length(); j++) {
            int diff = substr.charAt(j) - substr.charAt(j-1);
            if (diff != 1) ascending = false;
            if (diff != -1) descending = false;
        }

        return ascending || descending;
    }

    // 检查重复字符
    private static boolean hasRepeatedChars(String str, int repeatCount) {
        for (int i = 0; i <= str.length() - repeatCount; i++) {
            char current = str.charAt(i);
            boolean allSame = true;
            for (int j = 1; j < repeatCount; j++) {
                if (str.charAt(i + j) != current) {
                    allSame = false;
                    break;
                }
            }
            if (allSame) return true;
        }
        return false;
    }

    // 示例用法
    public static void main(String[] args) {
        String testPassword = "MyP@ssw0rd";
        List<String> errors = validatePassword(testPassword);

        if (errors.isEmpty()) {
            System.out.println("密码符合三级等保要求");
        } else {
            System.out.println("密码不符合要求，原因：");
            errors.forEach(System.out::println);
        }

        System.out.println(PersonInfoHandle.encryptS(testPassword));

    }
}
